package com.weepal.pavement.mqtt.demo.analysis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.weepal.pavement.mqtt.demo.analysis.dataSender.MQSender;
import com.weepal.pavement.mqtt.demo.analysis.dataSender.RedisSender;
import com.weepal.pavement.mqtt.demo.analysis.dataSender.SqlSender;
import com.weepal.pavement.mqtt.demo.analysis.resolver.JsonResolver;
import com.weepal.pavement.mqtt.demo.analysis.resolver.StringCuttingResolver;
import com.weepal.pavement.mqtt.demo.mapper.BasicMapper;
import com.weepal.pavement.mqtt.demo.vo.MqttDevices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 1.将信息和设备信息传入 √
 * 2.判断信息 json or String √
 * 3-1.json直接解析 ->结束 √
 * 3-2.String 是否定长 *
 * 4-1.定长直接切割 ->结束 *
 * 4-2.非定长判断是否累积数据 √
 * 5-1.累积数据做一个数据替换操作 ->6 √
 * 5-2.非累积数据直接操作 ->6 √
 * 6.将String数据转换成数组 GatewayDatavo[] √
 * 7.遍历数组，获取GatewayDatavo对应的字段 DeviceField √
 * 8.根据DeviceField 切割该条数据，生成与字段顺序对应的链表 √
 * 9.链表数据插入数据库 or redis or mq
 * <p>
 * 解析器入口
 *
 * @author mawen
 */
@Component
public class Analysiser {
    public static ThreadLocal<MqttDevices> devicesThreadLocal = new ThreadLocal<>();

    @Autowired
    private SqlSender sqlSender;
    @Autowired
    private RedisSender redisSender;
    @Autowired
    private MQSender mqSender;
//    private MqttDevices devices;

    private final static int STRINGTYPE = 1;
    private final static int JSONTYPE = 2;


    private final static int SQLTYPE = 1;
    private final static int REDISTYPE = 2;
    private final static int MQTYPE = 3;

    public void deal(String msg) {
//        this.devices = devices;
        MqttDevices devices = devicesThreadLocal.get();
        ConcurrentHashMap<String, LinkedList<String>> map = null;
        try {
            //判断该设备的数据解析类型，选用解析器，后续有新类型数据库定义datatype并编写一个新的解析器即可
            switch (devices.getDataType()) {
                case STRINGTYPE:
                    map = new StringCuttingResolver(msg, devices).resolve();
                    break;
                case JSONTYPE:
                    map = new JsonResolver(devices, msg).resolve();
                    break;
            }
            System.out.println(map);
            //这里定义解析器返回返回数据结构是ConcurrentHashMap<String, LinkedList<String>>
            //键是DeviceField的jsonkey，值是解析完数据
            //一个jsonkey对应多个要解析的字段，
            //"Data0":"xxxxxx...",Data0对应的内容可能会有多个寄存器的值，即多个字段
            //"a":{"b":123,"c":{"d":456}},json情况下a即为jsonkey,即最外层的key,可以获得字段b的数据，需要获得d的数据配置c.d这样的字段即可
            for (Map.Entry<String, LinkedList<String>> entry : map.entrySet()) {
                String jsonKey = entry.getKey();
                LinkedList<String> value = entry.getValue();
                if (value.isEmpty()) {
                    return;
                }
                //数据写入使用writeFields字段
                String fields = devices.getFields().get(jsonKey).getWriteFields();
                sendMsg(devices, jsonKey, value, fields);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            devicesThreadLocal.remove();
        }
    }

    public void sendMsg(MqttDevices devices, String key, LinkedList<String> v, String field) {
        switch (devices.getStrongeType()) {
            case SQLTYPE:
                sqlSender.send(devices, v, field);
                break;
            case REDISTYPE:
                redisSender.send(devices, field, key, v);
                break;
            case MQTYPE:
                mqSender.send(devices, field, key, v);
                break;
        }
    }
}
